package org.grow.leavejpa.controller;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.QueryResults;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.grow.leavejpa.dao.LeaveEntityJpa;
import org.grow.leavejpa.entity.*;
import org.grow.leavejpa.entity.QLeaveEntity;
import org.grow.leavejpa.entity.QUserInfo;
import org.grow.leavejpa.entity.enums.ApplyState;
import org.grow.leavejpa.entity.enums.AuditState;
import org.grow.leavejpa.exception.JulyException;
import org.hibernate.criterion.Junction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;

/**
 * @Author: xwg
 * @CreateDate: 21-6-9
 */
@RestController
@RequestMapping("/leaveAbout")
public class LeaveController {

    @Autowired
    private LeaveEntityJpa leaveEntityJpa;

    @PostMapping("/leave")
    public Boolean insert(@RequestBody LeaveEntity leaveEntity) {
        System.out.println(leaveEntity);
        leaveEntity.setLeaveId(0);
        UserInfo principal = (UserInfo) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        leaveEntity.setApplier(principal.getUsername());
        leaveEntity.setApplyState(ApplyState.saved);
        leaveEntity.setAuditState(AuditState.notAudit);

        leaveEntity.setApplyTime(LocalDateTime.now());
        leaveEntity.setAuditor(null);
        leaveEntity.setAuditorWord(null);

        leaveEntityJpa.save(leaveEntity);
        return true;
    }

    @Autowired
    private JPAQueryFactory jpaQueryFactory;

    @PostMapping("/leave/query/apply")
    public QueryPagedResults<LeaveEntity> applyQuery(@RequestBody ApplyLeavePaged applyLeavePaged) {

        Integer pageNum = applyLeavePaged.getPageNum();
        Integer pageSize = applyLeavePaged.getPageSize();
        Integer pageStart = (pageNum - 1) * pageSize;

        ApplyLeaveQueryCondition qc = applyLeavePaged.getQueryCondition();
//        JPAQueryFactory  Qentity
        QLeaveEntity l = QLeaveEntity.leaveEntity;
//        select * from LeaveEntiy l where l.name like

        BooleanBuilder builder = new BooleanBuilder();
//        动态条件
        /* private Integer leaveId;
    private String auditorSimilar;
    private LocalDateTime applyTimeStart;
    private LocalDateTime applyTimeEnd;
    private List<LeaveType> leaveTypes;
    private List<ApplyState> applyStates;*/
        if (qc.getLeaveId() != null && qc.getLeaveId() != 0) {

            builder.and(l.leaveId.eq(qc.getLeaveId()));
        }
        if (StringUtils.hasText(qc.getAuditorSimilar())) {

            builder.and(l.auditor.like(qc.getAuditorSimilar()));
        }
        if (qc.getApplyTimeStart() != null) {

            builder.and(l.applyTime.after(qc.getApplyTimeStart()));
        }
        if (qc.getApplyTimeEnd() != null) {

            builder.and(l.applyTime.before(qc.getApplyTimeEnd()));
        }
        if (!CollectionUtils.isEmpty(qc.getLeaveTypes())) {

            builder.and(l.leaveType.in(qc.getLeaveTypes()));
        }
        if (!CollectionUtils.isEmpty(qc.getApplyStates())) {

            builder.and(l.applyState.in(qc.getApplyStates()));
        }

// 静态条件
        UserInfo principal = (UserInfo) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        builder.and(l.applier.eq(principal.getUsername()));

        QueryResults<LeaveEntity> entityQueryResults = jpaQueryFactory.selectFrom(l)
                .where(builder)
                .orderBy(l.leaveId.desc())
                .offset(pageStart)
                .limit(pageSize)
                .fetchResults();
        QueryPagedResults<LeaveEntity> queryPagedResults = new QueryPagedResults<LeaveEntity>();
        queryPagedResults.setResults(entityQueryResults.getResults());
        queryPagedResults.setTotal(entityQueryResults.getTotal());

        return queryPagedResults;

    }

    //    /leaveAbout/leave/apply/1 get LeaveEntity
    @GetMapping("/leave/apply/{leaveId}")
    public LeaveEntity applyFindOne(@PathVariable("leaveId") Integer leaveId) {

        LeaveEntity leaveEntity = leaveEntityJpa.findByLeaveId(leaveId);
        String applier = leaveEntity.getApplier();
        UserInfo principal = (UserInfo) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String username = principal.getUsername();
        if (!applier.equals(username))
            throw new JulyException("您不是请假人，不能查看别人的请假条");

        return leaveEntity;
    }

    //    /leaveAbout/leave/modify put
    @PutMapping("/leave/modify")
    public Boolean modify(@RequestBody LeaveEntity leaveEntity) {


        if (leaveEntity.getApplyState() != ApplyState.saved)
            throw new JulyException("修改只能修改未提交状态的请假条");
        if (leaveEntity.getAuditState() != AuditState.notAudit)
            throw new JulyException("修改只能修改未审核状态的请假条");
        leaveEntityJpa.save(leaveEntity);
//        Integer leaveId = leaveEntity.getLeaveId();
//        LeaveEntity byLeaveId = leaveEntityJpa.findByLeaveId(leaveId);
//        if (byLeaveId == null ) throw new JulyException("该数据不存在");
//        byLeaveId.setReason(leaveEntity.getReason());
//        byLeaveId.setStartTime(leaveEntity.getStartTime());
//        byLeaveId.setEndTime(leaveEntity.getEndTime());
//        byLeaveId.setLeaveType(leaveEntity.getLeaveType());
//        leaveEntityJpa.save(byLeaveId);
        return true;

    }

    //    /leaveAbout/leave/submit/{leaveId} put
    @PutMapping("/leave/submit/{leaveId}")
    public Boolean submit(@PathVariable("leaveId") Integer leaveId) {

        LeaveEntity leaveEntity = leaveEntityJpa.findByLeaveId(leaveId);
        if (leaveEntity == null) {
            throw new JulyException("待提交的请假条不存在");
        }
        if (leaveEntity.getApplyState() != ApplyState.saved) {
            throw new JulyException("只有处于未提交状态未审核状态的请假条才可以提交");
        }
        if (leaveEntity.getAuditState() != AuditState.notAudit) {
            throw new JulyException("只有处于未提交状态未审核状态的请假条才可以提交");
        }
        leaveEntity.setApplyState(ApplyState.submitted);
        leaveEntity.setApplyTime(LocalDateTime.now());
        leaveEntityJpa.save(leaveEntity);
        return true;
    }

    //    /leave/query/audit post
    @PostMapping("/leave/query/audit")
    public QueryPagedResults<LeaveEntity> auditQuery(@RequestBody AuditLeavePaged auditLeavePaged) {
        Integer pageNum = auditLeavePaged.getPageNum();
        Integer pageSize = auditLeavePaged.getPageSize();
        Integer pageStart = (pageNum - 1) * pageSize;
        AuditLeaveQueryCondition qc = auditLeavePaged.getQueryCondition();
        QLeaveEntity l = QLeaveEntity.leaveEntity;


        BooleanBuilder builder = new BooleanBuilder();

        /*
        *     private String applierSimilar;
        *  private Integer leaveId;
    private LocalDateTime applyTimeEnd;
    private LocalDateTime applyTimeStart;
    private List<AuditState> auditStates;

    private List<LeaveType> leaveTypes;*/

        if (StringUtils.hasText(qc.getApplierSimilar())) {

            builder.and(l.applier.like(qc.getApplierSimilar()));
        }
        if (qc.getLeaveId() != null && qc.getLeaveId() != 0) {

            builder.and(l.leaveId.eq(qc.getLeaveId()));
        }
        if (qc.getApplyTimeEnd() != null) {

            builder.and(l.applyTime.before(qc.getApplyTimeEnd()));
        }
        if (qc.getApplyTimeStart() != null) {

            builder.and(l.applyTime.after(qc.getApplyTimeStart()));
        }
        if (!CollectionUtils.isEmpty(qc.getAuditStates())) {

            builder.and(l.auditState.in(qc.getAuditStates()));
        }
        if (!CollectionUtils.isEmpty(qc.getLeaveTypes())) {

            builder.and(l.leaveType.in(qc.getLeaveTypes()));
        }

        builder.and(l.applyState.eq(ApplyState.submitted));

        QueryResults<LeaveEntity> fetchResults = jpaQueryFactory.selectFrom(l)
                .where(builder)
                .orderBy(l.applyTime.desc())
                .offset(pageStart)
                .limit(pageSize)
                .fetchResults();

        QueryPagedResults<LeaveEntity> pagedResults = new QueryPagedResults<>();
        pagedResults.setResults(fetchResults.getResults());
        pagedResults.setTotal(fetchResults.getTotal());
        return pagedResults;


    }

    //    /leaveAbout/leave/audit/{leaveId}
    @GetMapping("/leave/audit/{leaveId}")
    public LeaveEntity auditFindOne(@PathVariable("leaveId") Integer leaveId) {
        LeaveEntity leaveEntity = leaveEntityJpa.findByLeaveId(leaveId);
        if (leaveEntity.getApplyState() != ApplyState.submitted)
            throw new JulyException("处于非已提交的状态的请假条，不允许审核人员查看");
        return leaveEntity;
    }

    //    /leave/audit/failed put
    @PutMapping("/leave/audit/failed")
    public Boolean auditFailed(@RequestBody LeaveEntity leaveEntity) {
        Integer leaveId = leaveEntity.getLeaveId();
        String auditorWord = leaveEntity.getAuditorWord();
        LeaveEntity leaveEntityReal = leaveEntityJpa.findByLeaveId(leaveId);
//        已提交未审核状态
        if (leaveEntityReal.getApplyState() != ApplyState.submitted)
            throw new JulyException("待审核的表单不处于已提交未审核状态，不能审核失败");
        if (leaveEntityReal.getAuditState() != AuditState.notAudit)
            throw new JulyException("待审核的表单不处于已提交未审核状态，不能审核失败");
        leaveEntityReal.setAuditorWord(auditorWord);
//        UserInfo principal = (UserInfo) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        leaveEntityReal.setAuditor(SecurityContextHolder.getContext().getAuthentication().getName());
        leaveEntityReal.setAuditState(AuditState.auditFailed);

        leaveEntityJpa.save(leaveEntityReal);
        return true;
    }

    //    /leave/audit/succeed put
    @PutMapping("/leave/audit/succeed")
    public Boolean auditSucceed(@RequestBody LeaveEntity leaveEntity) {
        Integer leaveId = leaveEntity.getLeaveId();
        String auditorWord = leaveEntity.getAuditorWord();
        LeaveEntity leaveEntityReal = leaveEntityJpa.findByLeaveId(leaveId);
//        已提交未审核状态
        if (leaveEntityReal.getApplyState() != ApplyState.submitted)
            throw new JulyException("待审核的表单不处于已提交未审核状态，不能审核成功");
        if (leaveEntityReal.getAuditState() != AuditState.notAudit)
            throw new JulyException("待审核的表单不处于已提交未审核状态，不能审核成功");
        leaveEntityReal.setAuditorWord(auditorWord);
//        UserInfo principal = (UserInfo) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        leaveEntityReal.setAuditor(SecurityContextHolder.getContext().getAuthentication().getName());
        leaveEntityReal.setAuditState(AuditState.auditSucceed);

        leaveEntityJpa.save(leaveEntityReal);
        return true;
    }
//    leave/confirm/{leaveId}
    @PutMapping("leave/confirm/{leaveId}")
    public Boolean confirm(@PathVariable("leaveId") Integer leaveId){
        LeaveEntity leaveEntity = leaveEntityJpa.findByLeaveId(leaveId);
        if (leaveEntity.getApplyState()!=ApplyState.submitted){
            throw new JulyException("待确认的请假条一定是已提交状态，不然不能终结");
        }
        if (leaveEntity.getAuditState() == AuditState.notAudit){
            throw new JulyException("不能终结，现在还没审核完毕");
        }
        leaveEntity.setApplyState(ApplyState.ended);
        leaveEntityJpa.save(leaveEntity);
        return true;
    }

}
